/**
 * AIChat吉PT - Chat吉PT用户脚本
 * 为Box3代码编辑器提供AI辅助功能
 */

// Import components and utilities
import {
  addStyleToHead,
  hasFocus,
  scrollToTop,
  setupCopyOnClick,
} from "./utils/domUtils";
import { getPromptByType } from "./utils/promptTemplates";
import {
  updateVirtualFileSystem,
  getAllFileContents,
  findSymbolsInCode,
} from "./utils/fileUtils";
import {
  setupUIComponents,
  updateChatContent,
  updateChatHeader,
  showAiPanel,
} from "./components/UIComponents";
import {
  registerEditorActions,
  registerColorProviders,
  setupJavaScriptOptions,
  registerCodeLensProvider,
  registerQuickFixProvider,
  updateVirtualFileSystem as monacoUpdateFileSystem,
  setupAutoFormatOnSave,
  setupAutoFormatOnEnter,
  setupBracketPairColorization,
  setupCustomJavaScriptTheme,
  setupErrorDecorations,
  setupTypeScriptStrictnessOptions,
  setupCustomSaveCommand,
  setupRunShortcut,
} from "./components/MonacoIntegration";
import {
  chatRun,
  chatCustomizeRun,
  getFileDictCode,
  handleMessageReceive,
} from "./components/EditorActions";
import { setupErrorList } from "./components/EditorErrorList";
import { setupErrorAIHelper } from "./components/ErrorAIHelper";
import { setupConsoleCleaner } from "./components/ConsoleCleaner";
import {
  generatePrompt,
  fetchUserInfo,
  sendChatRequest,
} from "./services/apiService";
import { showNotification } from "./monaco/utils";
import { registerMonacoInlineCompletionProvider } from "./monaco/inlineCompletionsProvider";

/**
 * Main script entry point
 */
(function () {
  "use strict";

  // Expose jQuery to the unsafeWindow
  unsafeWindow.$ = $;

  // Global references to editor components
  let monacoController;
  let gameUIEditor;
  let editObk;
  let userInfo;
  let ui;
  let errorList;
  let terrainConfigRendered = false;

  // Monitor for editor access
  // Set this variable in the global scope so we can check for it
  unsafeWindow.box3EditCore = null;

  // Property descriptor to capture the editor instance
  let editorCaptured = false;
  Object.defineProperty(Object.prototype, "permissionController", {
    get: function () {
      return this._permissionController;
    },
    set: function (v) {
      this._permissionController = v;
      if (!editorCaptured && this && this.codeEditorController) {
        unsafeWindow.box3EditCore = this;
        editorCaptured = true;
        console.log("Editor instance captured successfully");
      }
      return v;
    },
    configurable: true,
  });

  // Track mouse position for menu positioning
  window.addEventListener("mousemove", function (e) {
    window.lastMouseEvent = e;
  });

  // Initialize UI components
  let __next__root = setInterval(() => {
    try {
      // Handle message events
      window.addEventListener("message", handleMessageReceive, false);

      clearInterval(__next__root);
    } catch (error) {
      console.error("初始化UI组件失败:", error);
    }
  }, 100);

  // Wait for Monaco editor to be ready
  let editorInterval = setInterval(() => {
    try {
      // First check if csfrw42e is defined
      if (!unsafeWindow.box3EditCore) {
        return;
      }

      // Then check if the Monaco editor is ready
      if (
        unsafeWindow.box3EditCore.codeEditorController &&
        unsafeWindow.box3EditCore.codeEditorController.monacoController &&
        unsafeWindow.box3EditCore.codeEditorController.monacoController
          .monaco &&
        unsafeWindow.box3EditCore.codeEditorController.monacoController.monaco
          .editor &&
        unsafeWindow.box3EditCore.game &&
        unsafeWindow.box3EditCore.game.state &&
        unsafeWindow.box3EditCore.game.state.ready
      ) {
        clearInterval(editorInterval);

        // Store references to editor components
        monacoController = unsafeWindow.box3EditCore.codeEditorController;
        gameUIEditor = unsafeWindow.box3EditCore.gameUIEditor;
        editObk =
          monacoController.monacoController.monaco.editor.getEditors()[0];

        // Expose to unsafeWindow for script access
        unsafeWindow.ChatJPTmonacoController = monacoController;
        unsafeWindow.ChatJPTgameUIEditor = gameUIEditor;
        unsafeWindow.editObk = editObk;

        // Register editor actions
        registerEditorActions(monacoController, chatRunWrapper);

        // Register color providers
        registerColorProviders(monacoController);

        // Set up JavaScript options
        setupJavaScriptOptions(monacoController);

        // Register code lens provider
        registerCodeLensProvider(monacoController, chatRunWrapper);

        // Register quick fix provider
        registerQuickFixProvider(monacoController, chatCustomizeRunWrapper);

        // Setup error decorations with inline messages
        setupErrorDecorations(monacoController);

        // Setup auto format on Enter
        setupAutoFormatOnEnter(monacoController);

        // Setup custom save command to format code on Ctrl/Cmd+S
        setupCustomSaveCommand(monacoController);

        // Setup F5 shortcut to run the map
        setupRunShortcut(monacoController);

        // Setup error list component
        errorList = setupErrorList(
          monacoController.monacoController.monaco,
          editObk,
          chatCustomizeRunWrapper
        );

        // Setup AI help for error logs in debug panel
        setupErrorAIHelper(chatCustomizeRunWrapper);

        // Setup console cleaner
        setupConsoleCleaner();

        // Setup click-to-copy functionality for animated labels
        setupCopyOnClick("animated-block_label__qqojH", showNotification);

        // Verify error list is in the correct container after a short delay
        setTimeout(() => {
          // Setup custom JavaScript syntax highlighting theme
          setupCustomJavaScriptTheme(monacoController);

          // Setup TypeScript strictness options
          setupTypeScriptStrictnessOptions(monacoController);

          // Setup inline completion provider
          registerMonacoInlineCompletionProvider(monacoController);

          const errorListElement = document.querySelector(
            ".error-list-container"
          );
          const editorWrapper = document.querySelector(
            ".script-editor_scriptEditorWrapper__zjjus"
          );

          if (
            errorListElement &&
            editorWrapper &&
            !editorWrapper.contains(errorListElement)
          ) {
            console.log("Re-attaching error list to script editor wrapper");
            if (errorListElement.parentNode) {
              errorListElement.parentNode.removeChild(errorListElement);
            }
            editorWrapper.appendChild(errorListElement);
          }
        }, 1000);

        // Fetch user information
        const authHeader =
          unsafeWindow.box3EditCore.brpc &&
          unsafeWindow.box3EditCore.brpc.headers
            ? unsafeWindow.box3EditCore.brpc.headers.auth
            : "";
        // Create and initialize UI components
        ui = setupUIComponents(chatRunWrapper, chatCustomizeRunWrapper);

        if (authHeader) {
          fetchUserInfo(authHeader)
            .then((result) => {
              userInfo = result;
              updateChatHeader(userInfo);
            })
            .catch((error) => {
              console.error("获取用户信息失败:", error);
            });
        } else {
          console.warn("Auth header not available for user info fetch");
        }

        // Set up virtual file system
        updateVirtualFileSystem();

        // Add change listener to update virtual files
        editObk.onDidChangeModelContent(() => {
          updateVirtualFileSystem();
        });

        // Render the TerrainPanelConfig component
        renderTerrainPanelConfig();
      }
    } catch (error) {
      console.error(
        "初始化编辑器失败:",
        error,
        "State:",
        unsafeWindow.box3EditCore ? "csfrw42e exists" : "csfrw42e undefined"
      );
    }
  }, 500); // Increased interval to give more time for objects to initialize

  /**
   * Wraps chat run function with editor context
   * @param {number} type - Chat type ID
   * @param {boolean} isAll - Whether to include all code
   */
  function chatRunWrapper(type, isAll = false) {
    chatRun(type, isAll, editObk, chatWrapper, ui.elements, monacoController);
  }

  /**
   * Wraps custom chat run function with editor context
   * @param {number} type - Chat type ID
   * @param {string} customText - Custom text input
   */
  function chatCustomizeRunWrapper(type, customText) {
    chatCustomizeRun(type, customText, editObk, chatWrapper, ui.elements);
  }

  /**
   * Updates the virtual file system for Monaco
   */
  function updateVirtualFileSystem() {
    if (monacoController && monacoController._editorState) {
      monacoUpdateFileSystem(monacoController, monacoController._editorState);
    }
  }

  /**
   * Chat wrapper function that calls the API service
   * @param {string} value - The code or text to process
   * @param {number} type - The chat type ID
   * @param {string} cwl - Custom input
   * @param {string} valuel - Selected value
   * @param {boolean} isAll - Whether to include all code
   */
  async function chatWrapper(
    value,
    type,
    cwl = "",
    valuel = "",
    isAll = false
  ) {
    try {
      // Show AI panel and clear previous content
      showAiPanel(ui.elements);

      // Safely access auth header
      const authHeader =
        unsafeWindow.box3EditCore &&
        unsafeWindow.box3EditCore.brpc &&
        unsafeWindow.box3EditCore.brpc.headers
          ? unsafeWindow.box3EditCore.brpc.headers.auth
          : "";

      // Send chat request
      await sendChatRequest(value, type, cwl, valuel, isAll, {
        authHeader: authHeader,
        userId: userInfo?.data?.userId,
      });
    } catch (error) {
      console.error("Chat request failed:", error);
      // Show error message in chat window
      updateChatContent(
        "An error occurred while processing your request. Please try again."
      );
    }
  }

  // Function to render the TerrainPanelConfig component
  function renderTerrainPanelConfig() {
    if (terrainConfigRendered) return;

    try {
      // Create a script element to inject our TerrainPanel configuration code
      const script = document.createElement("script");
      script.innerHTML = `
        // Terrain Panel Configuration Script
        (function() {
          // Configuration values with default values
          const configs = {
            penSize: 5,      // Default brush size
            columnSize: 10,  // Default column size
            activeMode: 'pen' // Current active mode: 'pen' or 'column'
          };

          // 加载保存的设置
          function loadSavedSettings() {
            try {
              const savedSettings = localStorage.getItem('terrainPanelSettings');
              if (savedSettings) {
                const parsedSettings = JSON.parse(savedSettings);
                // 只更新有效的值
                if (typeof parsedSettings.penSize === 'number' && parsedSettings.penSize >= 1 && parsedSettings.penSize <= 256) {
                  configs.penSize = parsedSettings.penSize;
                }
                if (typeof parsedSettings.columnSize === 'number' && parsedSettings.columnSize >= 1 && parsedSettings.columnSize <= 64) {
                  configs.columnSize = parsedSettings.columnSize;
                }
              }
            } catch (error) {
              console.error('加载设置失败:', error);
            }
          }

          // 保存设置到本地存储
          function saveSettings() {
            try {
              localStorage.setItem('terrainPanelSettings', JSON.stringify({
                penSize: configs.penSize,
                columnSize: configs.columnSize
              }));
            } catch (error) {
              console.error("保存设置失败:", error);
            }
          }

          // Create UI elements
          function createConfigUI() {
            // 首先加载保存的设置
            loadSavedSettings();
            
            // Create container
            const configPanel = document.createElement('div');
            configPanel.className = 'terrain-panel-config';
            configPanel.style.position = 'absolute';
            configPanel.style.right = '-224px';
            configPanel.style.bottom = '0';
            configPanel.style.width = '210px';
            configPanel.style.padding = '12px';
            configPanel.style.backgroundColor = 'rgb(51 51 51 / 70%)';
            configPanel.style.borderRadius = '8px';
            configPanel.style.boxShadow = '0 2px 10px rgba(0, 0, 0, 0.1)';
            configPanel.style.zIndex = '1000';
            configPanel.style.display = 'flex';
            configPanel.style.flexDirection = 'column';
            configPanel.style.gap = '10px';

            // Pen size input
            const penSizeContainer = document.createElement('div');
            penSizeContainer.id = 'pen-size-container';
            penSizeContainer.style.display = 'flex';
            penSizeContainer.style.flexDirection = 'column';
            penSizeContainer.style.gap = '4px';
            
            const penSizeLabel = document.createElement('label');
            penSizeLabel.textContent = '笔刷宽度:';
            penSizeLabel.style.fontSize = '12px';
            penSizeLabel.style.color = '#d7d7d7';
            penSizeContainer.appendChild(penSizeLabel);
            
            // 创建滑动条和输入框的容器
            const penSizeInputContainer = document.createElement('div');
            penSizeInputContainer.style.display = 'flex';
            penSizeInputContainer.style.alignItems = 'center';
            penSizeInputContainer.style.gap = '5px';
            
            // 滑动条
            const penSizeSlider = document.createElement('input');
            penSizeSlider.type = 'range';
            penSizeSlider.min = '1';
            penSizeSlider.max = '256';
            penSizeSlider.value = configs.penSize;
            penSizeSlider.style.flex = '1';
            penSizeSlider.style.height = '10px';
            penSizeSlider.style.accentColor = 'rgb(255 129 0)';
            
            // 数字输入框
            const penSizeInput = document.createElement('input');
            penSizeInput.type = 'number';
            penSizeInput.value = configs.penSize;
            penSizeInput.min = '1';
            penSizeInput.max = '256';
            penSizeInput.style.padding = '2px 4px';
            penSizeInput.style.width = '48px';
            penSizeInput.style.borderRadius = '4px';
            penSizeInput.style.background = 'rgb(255 255 255 / 70%)';
            penSizeInput.style.border = '1px solid #ddd';
            
            // 同步滑动条和输入框的值，并立即应用设置
            penSizeSlider.addEventListener('input', function() {
              const value = parseInt(this.value);
              penSizeInput.value = value;
              configs.penSize = value;
              applySettings();
              // 保存设置
              saveSettings();
            });
            
            penSizeInput.addEventListener('change', function() {
              const value = parseInt(this.value);
              penSizeSlider.value = value;
              configs.penSize = value;
              applySettings();
              // 保存设置
              saveSettings();
            });
            
            penSizeInputContainer.appendChild(penSizeSlider);
            penSizeInputContainer.appendChild(penSizeInput);
            penSizeContainer.appendChild(penSizeInputContainer);
            configPanel.appendChild(penSizeContainer);

            // Column size input
            const columnSizeContainer = document.createElement('div');
            columnSizeContainer.id = 'column-size-container';
            columnSizeContainer.style.display = 'flex';
            columnSizeContainer.style.flexDirection = 'column';
            columnSizeContainer.style.gap = '4px';
            
            const columnSizeLabel = document.createElement('label');
            columnSizeLabel.textContent = '笔刷高度:';
            columnSizeLabel.style.fontSize = '12px';
            columnSizeLabel.style.color = '#d7d7d7';
            columnSizeContainer.appendChild(columnSizeLabel);
            
            // 创建滑动条和输入框的容器
            const columnSizeInputContainer = document.createElement('div');
            columnSizeInputContainer.style.display = 'flex';
            columnSizeInputContainer.style.alignItems = 'center';
            columnSizeInputContainer.style.gap = '5px';
            
            // 滑动条
            const columnSizeSlider = document.createElement('input');
            columnSizeSlider.type = 'range';
            columnSizeSlider.min = '1';
            columnSizeSlider.max = '128';
            columnSizeSlider.value = configs.columnSize;
            columnSizeSlider.style.flex = '1';
            columnSizeSlider.style.height = '10px';
            columnSizeSlider.style.accentColor = 'rgb(255 129 0)';
            
            // 数字输入框
            const columnSizeInput = document.createElement('input');
            columnSizeInput.type = 'number';
            columnSizeInput.value = configs.columnSize;
            columnSizeInput.min = '1';
            columnSizeInput.max = '64';
            columnSizeInput.style.padding = '2px 4px';
            columnSizeInput.style.width = '48px';
            columnSizeInput.style.borderRadius = '4px';
            columnSizeInput.style.background = 'rgb(255 255 255 / 70%)';
            columnSizeInput.style.border = '1px solid #ddd';
            
            // 同步滑动条和输入框的值，并立即应用设置
            columnSizeSlider.addEventListener('input', function() {
              const value = parseInt(this.value);
              columnSizeInput.value = value;
              configs.columnSize = value;
              applySettings();
              // 保存设置
              saveSettings();
            });
            
            columnSizeInput.addEventListener('change', function() {
              const value = parseInt(this.value);
              columnSizeSlider.value = value;
              configs.columnSize = value;
              applySettings();
              // 保存设置
              saveSettings();
            });
            
            columnSizeInputContainer.appendChild(columnSizeSlider);
            columnSizeInputContainer.appendChild(columnSizeInput);
            columnSizeContainer.appendChild(columnSizeInputContainer);
            configPanel.appendChild(columnSizeContainer);

            // 消息容器显示状态
            const messageContainer = document.createElement('div');
            messageContainer.id = 'terrain-config-message';
            messageContainer.style.padding = '4px';
            messageContainer.style.borderRadius = '4px';
            messageContainer.style.marginTop = '5px';
            messageContainer.style.fontSize = '10px';
            messageContainer.style.textAlign = 'center';
            messageContainer.style.display = 'none';
            configPanel.appendChild(messageContainer);

            // 根据当前模式显示相应的设置
            updateVisibleControls();

            return configPanel;
          }

          // 更新控件显示状态
          function updateVisibleControls() {
            const penContainer = document.getElementById('pen-size-container');
            const columnContainer = document.getElementById('column-size-container');
            
            if (configs.activeMode === 'pen') {
              if (penContainer) penContainer.style.display = 'flex';
              if (columnContainer) columnContainer.style.display = 'none';
            } else {
              if (penContainer) penContainer.style.display = 'none';
              if (columnContainer) columnContainer.style.display = 'flex';
            }
          }

          // Function to get React component instance
          function getReactElement(element) {
            if (!element) return null;
            const key = Object.keys(element).filter((v) => 
              v.startsWith("__reactInternalInstance$") || v.startsWith("__reactFiber$")
            )[0];
            return element[key];
          }

          // Function to apply settings
          function applySettings() {
            try {
              // 1. Get target element
              const terrainPanelElement = document.querySelector("[class*=terrainPanel_terrainPanel]");
              
              if (!terrainPanelElement) {
                throw new Error("请先打开地形面板");
              }

              // 2. Get React component instance
              const reactComponent = getReactElement(terrainPanelElement);
              
              if (!reactComponent || !reactComponent.return || !reactComponent.return.return || !reactComponent.return.return.stateNode) {
                throw new Error("获取组件失败");
              }

              const element = reactComponent.return.return.stateNode;

              // 3. Validate component state and methods
              if (typeof element.setState !== "function") {
                throw new Error("组件错误");
              }
              
              if (typeof element.state?.columnSize !== "number" || typeof element.state?.penSize !== "number") {
                throw new Error("属性错误");
              }

              // 4. Update component state - 不显示成功消息
              element.setState({
                penSize: configs.penSize,
                columnSize: configs.columnSize
              });
              
              // 成功时隐藏消息并保存设置
              hideMessage();
              saveSettings();
            } catch (error) {
              console.error("Failed to update terrain panel settings:", error.message);
              showMessage(error.message);
            }
          }

          // Function to show message - 只在错误时显示
          function showMessage(text) {
            const messageContainer = document.getElementById('terrain-config-message');
            if (!messageContainer) return;
            
            messageContainer.textContent = text;
            messageContainer.style.backgroundColor = 'rgba(220, 53, 69, 0.7)';
            messageContainer.style.color = '#fff';
            messageContainer.style.display = 'block';
            
            // 清除任何现有的超时
            if (messageContainer.timeoutId) {
              clearTimeout(messageContainer.timeoutId);
            }
            
            // 设置显示时间
            messageContainer.timeoutId = setTimeout(() => {
              messageContainer.style.display = 'none';
            }, 1500);
          }
          
          // 隐藏消息
          function hideMessage() {
            const messageContainer = document.getElementById('terrain-config-message');
            if (!messageContainer) return;
            
            messageContainer.style.display = 'none';
            
            if (messageContainer.timeoutId) {
              clearTimeout(messageContainer.timeoutId);
              messageContainer.timeoutId = null;
            }
          }

          // 监听图标点击状态
          function monitorIconState() {
            // 使用MutationObserver监听DOM变化
            const observer = new MutationObserver((mutations) => {
              mutations.forEach((mutation) => {
                if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
                  // 检查当前活跃的图标
                  const brushActive = document.querySelector('.terrainPanel_brushIcon__5dFgB.editor-common_icon__7pWt6');
                  const columnActive = document.querySelector('.terrainPanel_columnIcon__i0WDz.editor-common_icon__7pWt6');
                  
                  // 根据活跃的图标更新当前模式
                  if (brushActive) {
                    configs.activeMode = 'pen';
                   
                  } else if (columnActive) {
                    configs.activeMode = 'column';
               
                  }
                  
                  // 更新控件显示状态
                  updateVisibleControls();
                }
              });
            });
            
            // 观察整个文档的class变化
            observer.observe(document.body, {
              subtree: true,
              attributes: true,
              attributeFilter: ['class']
            });
            
            // 立即检查当前状态
            const brushActive = document.querySelector('.terrainPanel_brushIcon__5dFgB.editor-common_icon__7pWt6');
            const columnActive = document.querySelector('.terrainPanel_columnIcon__i0WDz.editor-common_icon__7pWt6');
            
            if (brushActive) {
              configs.activeMode = 'pen';
          
            } else if (columnActive) {
              configs.activeMode = 'column';
         
            }
            
            updateVisibleControls();
          }

          // 监听地形面板出现并应用设置
          function monitorPanelAppearance() {
            // 确保首先加载保存的设置
            loadSavedSettings();
            
            // 使用MutationObserver监听DOM变化
            const observer = new MutationObserver((mutations) => {
              // 检查地形面板是否出现
              const terrainPanel = document.querySelector("[class*=terrainPanel_terrainPanel]");
              if (terrainPanel) {
                // 应用保存的设置
               
                // 更新UI显示
                const penInput = document.querySelector('#pen-size-container input[type="number"]');
                const penSlider = document.querySelector('#pen-size-container input[type="range"]');
                if (penInput) penInput.value = configs.penSize;
                if (penSlider) penSlider.value = configs.penSize;
                
                const columnInput = document.querySelector('#column-size-container input[type="number"]');
                const columnSlider = document.querySelector('#column-size-container input[type="range"]');
                if (columnInput) columnInput.value = configs.columnSize;
                if (columnSlider) columnSlider.value = configs.columnSize;
                
                // 立即应用设置
                applySettings();
              }
            });
            
            // 观察整个文档的变化
            observer.observe(document.body, {
              childList: true,
              subtree: true
            });
          }

          // Initialize and add the config panel
          function init() {
            // Create MutationObserver to detect when the create panel appears or disappears
            const observer = new MutationObserver((mutations) => {
              const createPanel = document.querySelector(".create-panel_createPanelContainer__ULJs8");
              
              if (createPanel) {
                // If panel exists but our config isn't attached to it yet
                if (!createPanel.querySelector('.terrain-panel-config')) {
                  const configUI = createConfigUI();
                  createPanel.appendChild(configUI);
                  // 开始监听图标状态
                  monitorIconState();
                  // 监听地形面板出现并应用设置
                  monitorPanelAppearance();
                }
              } else {
                // Remove our config panel if it exists but create panel doesn't
                const configPanel = document.querySelector('.terrain-panel-config');
                if (configPanel) {
                  configPanel.remove();
                }
              }
            });
            
            // Start observing the entire document for changes
            observer.observe(document.body, {
              childList: true,
              subtree: true
            });
            
            // Check immediately on init
            const createPanel = document.querySelector(".create-panel_createPanelContainer__ULJs8");
            
            if (createPanel && !createPanel.querySelector('.terrain-panel-config')) {
              const configUI = createConfigUI();
              createPanel.appendChild(configUI);
              // 开始监听图标状态
              monitorIconState();
              // 监听地形面板出现并应用设置
              monitorPanelAppearance();
            }
          }

          // Start initialization
          init();
        })();
      `;

      document.body.appendChild(script);

      terrainConfigRendered = true;
      console.log("Terrain panel configuration script injected successfully");
    } catch (error) {
      console.error("Failed to render terrain panel configuration:", error);
    }
  }
})();
